module PulseWidthMeter (
  input rstn,
  input en,
  input clk_std,
  input clk_test,
  output reg [31:0] pulseWidth,
  output reg [31:0] dutyCycle
);


localparam T_std = 4'd5; // 5ns

// 获取en上升沿
wire pos_en;
reg [1:0] r_en;

always @(posedge clk_std, negedge rstn) begin
  if(!rstn)
    r_en <= 2'd0;
  else
    r_en <= {r_en[0], en};
end

assign pos_en = (!r_en[1]) & (r_en[0]);


// 获取待测时钟上升、下降沿
wire neg_clk_test;
wire pos_clk_test;
reg [1:0] r_clk_test;

always @(posedge clk_std, negedge rstn) begin
  if(!rstn)
    r_clk_test <= 2'd0;
  else
    r_clk_test <= {r_clk_test[0], clk_test};
end

assign neg_clk_test = (r_clk_test[1]) & (!r_clk_test[0]);
assign pos_clk_test = (!r_clk_test[1]) & (r_clk_test[0]);


// 高低电平计数
reg pos_start;
reg neg_start;
reg [31:0] pos_cnt;
reg [31:0] neg_cnt;

always @(posedge clk_std, negedge rstn) begin
  if(!rstn) begin
    pos_start <= 1'd0;
    neg_start <= 1'd0;
  end
  else if(pos_clk_test) begin
    neg_start <= 1'd0;
    if(pos_cnt == 32'd0)
      pos_start <= 1'd1;
    else
      pos_start <= pos_start;
  end
  else if(neg_clk_test) begin
    pos_start <= 1'd0;
    if(neg_cnt == 32'd0)
      neg_start <= 1'd1;
    else
      neg_start <= neg_start;
  end
  else begin
    pos_start <= pos_start;
    neg_start <= neg_start;
  end
end

always @(posedge clk_std, negedge rstn) begin
  if(!rstn)
    pos_cnt <= 32'd0;
  else if(pos_en)
    pos_cnt <= 32'd0;
  else if(pos_start)
    pos_cnt <= pos_cnt + 32'd1;
  else
    pos_cnt <= pos_cnt;
end

always @(posedge clk_std, negedge rstn) begin
  if(!rstn)
    neg_cnt <= 32'd0;
  else if(pos_en)
    neg_cnt <= 32'd0;
  else if(neg_start)
    neg_cnt <= neg_cnt + 32'd1;
  else
    neg_cnt <= neg_cnt;
end


// 计算脉宽
wire cnt_done;

assign cnt_done = !(pos_start | neg_start) & (pos_cnt != 32'd0) & (neg_cnt != 32'd0);

always @(posedge clk_std, negedge rstn) begin
  if(!rstn)
    pulseWidth <= 32'd0;
  else if(cnt_done)
    pulseWidth <= pos_cnt * T_std;
  else
    pulseWidth <= 32'd0;
end


// 计算占空比
reg [45:0] tmp_mult;

always @(posedge clk_std, negedge rstn) begin
  if(!rstn)
    tmp_mult <= 46'd0;
  else if(cnt_done)
    tmp_mult <= 14'd10_000 * pos_cnt;
  else
    tmp_mult <= 46'd0;
end

always @(posedge clk_std, negedge rstn) begin
  if(!rstn)
    dutyCycle <= 32'd0;
  else if(cnt_done)
    dutyCycle <= tmp_mult / (pos_cnt + neg_cnt);
  else
    dutyCycle <= 32'd0;
end


endmodule